﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Web.Mvc;
using Nop.Services.Media;
using Nop.Services.Security;
using Nop.Web.Framework.Controllers;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;

namespace Nop.Admin.Controllers
{
    [AdminAuthorize]
    public partial class BlobPictureManagerController : BaseNopController
    {
        private readonly IPictureService _pictureService;
        private readonly IPermissionService _permissionService;

        public BlobPictureManagerController(IPictureService pictureService,
             IPermissionService permissionService)
        {
            this._pictureService = pictureService;
            this._permissionService = permissionService;
        }

        public ActionResult List()
        {
            return View();
        }

        public ActionResult ListFolderContent(string folder = "", string marker = "")
        {
            if (folder == "/")
                folder = "";
            var token = new BlobContinuationToken();
            var currentToken = new BlobContinuationToken();
            if (!String.IsNullOrEmpty(marker))
            {
                currentToken.NextMarker = marker;
                currentToken.TargetLocation = StorageLocation.Primary;
            }
            else
                currentToken = null;
            var folderContent = _pictureService.ListFolderContent(folder, null, currentToken, out token);
            if (token != null)
                marker = token.NextMarker;
            else
                marker = "";
            var output = new List<FileFolderObject>();
            var count = 0;
            foreach (var blobItem in folderContent)
            {
                if (blobItem is CloudBlobDirectory)
                {
                    var directory = PrepareFileFolderObjectFromDirectory(blobItem as CloudBlobDirectory);
                    if (directory != null)
                    {
                        output.Add(directory);
                        count++;
                    }
                }
                else if (blobItem is CloudBlockBlob)
                {
                    var item = PrepareFileFolderObjectFromBlob(blobItem as CloudBlockBlob);
                    if (item != null)
                    {
                        output.Add(item);
                        count++;
                    }
                }
            }
            var json = Json(new
            {
                folderContent = output,
                marker = marker,
                count = count
            });
            json.MaxJsonLength = 50000000;

            return json;
        }

        [NonAction]
        private FileFolderObject PrepareFileFolderObjectFromDirectory(CloudBlobDirectory dir)
        {
            if (!dir.Prefix.StartsWith("Thumb/"))
            {
                var name = dir.Prefix;
                if (dir.Parent != null && !String.IsNullOrEmpty(dir.Parent.Prefix)) {
                    name = name.Remove(0, dir.Parent.Prefix.Length);
                }

                name = name.Replace("/", "");
                return new FileFolderObject
                {
                    Name = name,
                    Type = "folder",
                    Path = dir.Uri.AbsoluteUri,
                    Location = dir.Prefix
                };
            }
            return null;
        }

        [NonAction]
        private FileFolderObject PrepareFileFolderObjectFromBlob(CloudBlockBlob item)
        {
            var name = item.Name;
            if (name == "dir.config")
                return null;
            var itemParent = item.Parent;
            var size = "";
            var dimension = "";

            if (itemParent != null && !String.IsNullOrEmpty(itemParent.Prefix))
            {
                name = name.Replace(itemParent.Prefix, "");
            }

            if (item.Metadata.ContainsKey("width") && item.Metadata.ContainsKey("height"))
            {
                dimension = item.Metadata["width"] + " x " + item.Metadata["height"];
            }

            if (item.Properties.Length < 1024)
            {
                size = item.Properties.Length.ToString() + "bytes";
            }
            else if (item.Properties.Length < 1048576)
            {
                size = ((double)(item.Properties.Length / 1024)).ToString() + "KB";
            }
            else if (item.Properties.Length < 1073741824)
            {
                size = ((double)(item.Properties.Length / 1048576)).ToString() + "MB";
            }
            else
            {
                size = ((double)(item.Properties.Length / 1073741824)).ToString() + "GB";
            }
            
            return new FileFolderObject
            {
                Name = name,
                Type = item.Properties.ContentType,
                Path = item.Uri.AbsoluteUri,
                Location = item.Name,
                ThumbPath = item.Uri.AbsoluteUri.Replace(name, "") + "Thumb/" + name,
                Size = size,
                Dimension = dimension,
                LastModified = item.Properties.LastModified.Value.LocalDateTime.ToString("yyyy/MM/dd hh:mm")
            };
        }

        [HttpPost]
        public ActionResult UploadImageToFolder(string folder = "")
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.UploadPictures) || !_permissionService.Authorize(StandardPermissionProvider.ManagePictures))
                return Json( new { success = false, error = "You do not have required permissions." }, "text/plain");

            Stream stream = null;
            var fileName = "";
            var contentType = "";

            if (String.IsNullOrEmpty(Request["image"]))
            {
                HttpPostedFileBase httpPostedFile = Request.Files[0];
                if (httpPostedFile == null)
                    throw new ArgumentException("No file uploaded");
                stream = httpPostedFile.InputStream;
                fileName = Path.GetFileName(httpPostedFile.FileName);
                contentType = httpPostedFile.ContentType;
            }
            else
            {
                //Webkit, Mozilla
                stream = Request.InputStream;
                fileName = Request["image"];
            }
            var fileBinary = new byte[stream.Length];
            stream.Read(fileBinary, 0, fileBinary.Length);

            var fileExtension = Path.GetExtension(fileName);
            if (!String.IsNullOrEmpty(fileExtension))
                fileExtension = fileExtension.ToLowerInvariant();
            //contentType is not always available 
            //that's why we manually update it here
            //http://www.sfsu.edu/training/mimetype.htm
            if (String.IsNullOrEmpty(contentType))
            {
                switch (fileExtension)
                {
                    case ".bmp":
                        contentType = "image/bmp";
                        break;
                    case ".gif":
                        contentType = "image/gif";
                        break;
                    case ".jpeg":
                    case ".jpg":
                    case ".jpe":
                    case ".jfif":
                    case ".pjpeg":
                    case ".pjp":
                        contentType = "image/jpeg";
                        break;
                    case ".png":
                        contentType = "image/png";
                        break;
                    case ".tiff":
                    case ".tif":
                        contentType = "image/tiff";
                        break;
                    default:
                        break;
                }
            }
            CloudBlockBlob savedFile = null;
            FileFolderObject item = null;
            bool saveSuccess = _pictureService.SaveUploadedPictureToFolder(folder, fileBinary, null, fileName, contentType, out savedFile);
            if (saveSuccess && savedFile != null)
                item = PrepareFileFolderObjectFromBlob(savedFile);

            return Json(new
            {
                success = saveSuccess,
                file = item
            });
        }

        [HttpPost]
        public ActionResult DeleteImageFromFolder(string path = "")
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.UploadPictures) || !_permissionService.Authorize(StandardPermissionProvider.ManagePictures))
                return Json(new { success = false, error = "You do not have required permissions." }, "text/plain");
            if (String.IsNullOrEmpty(path))
                return Json(new { success = false, error = "Unable to identify file." }, "text/plain");
            if (!_pictureService.DeleteUploadedImage(path))
                return Json(new { success = false, error = "Unable to delete file." }, "text/plain");

            return Json(new { success = true, error = "Successfully deleted file." }, "text/plain");
        }

        [HttpPost]
        public ActionResult CreateFolder(string path = "")
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.UploadPictures) || !_permissionService.Authorize(StandardPermissionProvider.ManagePictures))
                return Json(new { success = false, error = "You do not have required permissions." }, "text/plain");
            if (String.IsNullOrEmpty(path))
                return Json(new { success = false, error = "Unable to create folder." }, "text/plain");
            CloudBlobDirectory createdFolder = null;
            FileFolderObject folder = null;
            if (!_pictureService.CreateFolder(path, out createdFolder))
                return Json(new { success = false, error = "Unable to create folder." }, "text/plain");

            if (createdFolder != null)
                folder = PrepareFileFolderObjectFromDirectory(createdFolder);

            return Json(new { 
                success = true, 
                folder = folder
            });
        }
        [HttpPost]
        public ActionResult RemoveFolder(string path = "")
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.UploadPictures) || !_permissionService.Authorize(StandardPermissionProvider.ManagePictures))
                return Json(new { success = false, error = "You do not have required permissions." }, "text/plain");
            if (String.IsNullOrEmpty(path))
                return Json(new { success = false, error = "Unable to remove folder." }, "text/plain");
            if (!_pictureService.DeleteFolder(path))
                return Json(new { success = false, error = "Unable to remove folder." }, "text/plain");

            return Json(new { success = true }, "text/plain");
        }
    }

    public partial class FileFolderObject
    {
        public string Name { get; set; }
        public string Type { get; set; }
        public string Path { get; set; }
        public string Location { get; set; }
        public string ThumbPath { get; set; }
        public string Size { get; set; }
        public string Dimension { get; set; }
        public string LastModified { get; set; }
    }
}
